package com.jn.interceptor;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.jn.ann.Entity;
import com.jn.ann.WebObject;
import com.jn.ann.WebObjectScheme;
import com.jn.ann.WebResolver;
import com.jn.dao.BaseMapper;
import com.jn.entity.BaseEntity;
import com.jn.entity.EntityLimit;
import com.jn.entity.EntityQuery;
import com.jn.entity.EntityScheme;
import com.jn.entity.transverter.Transverter;
import com.jn.tools.DataSearchTools;

public class ObjectPackningInterceptor implements HandlerInterceptor {

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception e) throws Exception {
		
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mv) throws Exception {
		
	}
	
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
		HandlerMethod method = (HandlerMethod) object;
		
		if(method.getMethodAnnotation(WebResolver.class) != null){
			BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
			BaseMapper baseMapper = (BaseMapper) factory.getBean("baseMapper");
			
			if(method.getMethodAnnotation(WebResolver.class).resolverObject().length > 0){
				for(WebObject webObject : method.getMethodAnnotation(WebResolver.class).resolverObject()){
					Class<? extends BaseEntity> objClzz = webObject.objClass();
					String clzzName = objClzz.toString().substring(objClzz.toString().lastIndexOf(".") + 1);
					String objName = clzzName.substring(0, 1).toLowerCase() + clzzName.substring(1);
					String tableName = webObject.objClass().getAnnotation(Entity.class).tableName();
					
					Set<String> colNames = baseMapper.selectColNames(tableName);
					
					Map<String,Transverter> objTransverterMap = new HashMap<String,Transverter>();
					if(!webObject.scheme().trim().equals("")){
						Field[] fields = objClzz.getDeclaredFields();
						for(Field field : fields){
							if(field.getAnnotation(WebObjectScheme.class) != null){
								String fieldName = field.getAnnotation(WebObjectScheme.class).name();
								if(webObject.scheme().trim().equals(fieldName)){
									Object o = field.get(objClzz);
									if(o instanceof EntityScheme[]){
										EntityScheme[] schemes = (EntityScheme[]) o;
										for(EntityScheme s : schemes){
											if(s.getTransverter() != null){
												if(colNames.contains(s.getColName())){
													objTransverterMap.put(s.getColName(), s.getTransverter());
												}else{
													System.err.println("警告： web对象封装方案出现错误，请检查方案与对象列");
												}
											}
										}
									}else{
										System.err.println("警告： web对象封装方案出现错误，请检查方案结构，按默认方案封装对象");
									}
								}
							}
						}
					}
					
					BaseEntity be = objClzz.newInstance();
					for(String colName : colNames){
						String requestName = objName + "." + colName;
						if(request.getParameter(requestName) != null){
							if(objTransverterMap.get(colName) != null){
								be.setKV(colName, objTransverterMap.get(colName).transverter(request.getParameter(requestName)));
							}else{
								be.setKV(colName, request.getParameter(requestName));
							}
						}
					}
					request.setAttribute(objName, be);
				}
			}

			if(method.getMethodAnnotation(WebResolver.class).search()){
				List<EntityQuery> queryList = new ArrayList<EntityQuery>();
				
				Enumeration<String> names = request.getParameterNames();
				while(names.hasMoreElements()){
					String name = names.nextElement();
					if(name.contains("search_")){
						request.setAttribute(name, request.getParameter(name));
						String key = name.substring(name.indexOf("_")+1, name.lastIndexOf("_"));
						String operation = name.substring(name.lastIndexOf("_")+1);
						String val = request.getParameter(name).trim();
						if(!val.equals("") && val != null){
							queryList.add(DataSearchTools.operationSymbol(key, operation, val));
						}
					}
				}
				
				if(queryList.size() > 0){
					EntityQuery[] querys = new EntityQuery[queryList.size()];
					for(int i = 0; i < queryList.size(); i++){
						querys[i] = queryList.get(i);
					}
					request.setAttribute("querys", querys);
				}else{
					request.setAttribute("querys", new EntityQuery[0]);
				}
			}
			
			if(method.getMethodAnnotation(WebResolver.class).limit()){
				Integer page = Integer.valueOf(request.getParameter("page"));
				Integer limit = Integer.valueOf(request.getParameter("limit"));
				
				Integer start = page == 1 ? 0 : ( page - 1 ) * limit;
				EntityLimit entityLimit = new EntityLimit(start, limit);
				request.setAttribute("limit", entityLimit);
			}
		}
		return true;
	}

}
